package prober;

import java.util.ArrayList;
import java.util.List;

import queries.Dictionary;
import queries.Query;
import queries.QueryExecutor;

/**
 * Main QProber implementation.
 * 
 * @author Vika
 * @author ak2765
 */
public class Classifier {

	Category root;

	QueryExecutor executor;

	public Classifier(QueryExecutor executor) {
		this.executor = executor;

		Category hardware = new Category("Hardware", Dictionary.hardware_qs);
		Category programming = new Category("Programming", Dictionary.programming_qs);
		Category computers = new Category("Computers", Dictionary.computers_qs);
		computers.addChild(hardware);
		computers.addChild(programming);
		
		Category basketball = new Category("Basketball", Dictionary.basketball_qs);
		Category soccer = new Category("Soccer", Dictionary.soccer_qs);
		Category sports = new Category("Sports", Dictionary.sports_qs);
		sports.addChild(basketball);
		sports.addChild(soccer);


		Category fitness = new Category("Fitness", Dictionary.fitness_qs);
		Category disease = new Category("Disease", Dictionary.disease_qs);
		Category health = new Category("Health", Dictionary.health_qs);
		health.addChild(fitness);
		health.addChild(disease);


		root = new Category("Root", Query.EMPTY_QUERY);
		root.addChild(computers);
		root.addChild(health);
		root.addChild(sports);
	}

	public List<Category> QProbe(String url, double specificity, int coverage) {
		if (url.indexOf(".") == -1) {
			throw new IllegalArgumentException(
					"Please pass a valid domain ( *.org, *.edu, *.com, etc) ");
		}

		return Classify(root, url, coverage, specificity, 1);
	}

	private List<Category> Classify(Category root, String url, int t_ec,
			double t_es, double especificity) {
		
		List<Category> result = new ArrayList<Category>();
		if (root.isLeaf()) {
			result.add(root);
			return result;
		}

		List<Category> children = root.getChildren();

		// coverage vector
		int[] eCoverage = new int[children.size()];

		// specificity vector
		double[] eSpecificity = new double[children.size()];

		int totalCoverage = 0;

		// populate coverage vector for each child category
		for (int i = 0; i< children.size(); ++i) {
			Category child = children.get(i);
			//Logger.info("\nPopulating coverage vector for category: " + child.getCategoryName());
			
			Query[] qs = child.getQueries();

			int coverage = 0;
			queries.DocumentSample sample = new queries.DocumentSample();

			for (int j = 0; j < qs.length; ++j) {

				coverage += executor.executeQuery(url, qs[j], sample);
			}

			eCoverage[i] = coverage;
			totalCoverage += coverage;
		    root.setDocSample(sample);

		}

		// populate specificity vector for each child category
		for (int i = 0; i < children.size(); ++i) {
			eSpecificity[i] = especificity * eCoverage[i] / totalCoverage;
		}

		for (int i = 0; i < children.size(); ++i) {
			Category child = children.get(i);

			if (eCoverage[i] >= t_ec && eSpecificity[i] >= t_es) {

				result.add(root);
				result.addAll(Classify(child, url, t_ec, t_es, eSpecificity[i]));
			}
		}

		if (result.isEmpty())
			result.add(root);

		return result;
	}

}
